#include "membackend/accurateBank.h"
#include "membackend/accurateIRankTiming.h"
#include "membackend/accurateAddressMappingConfig.h"




Bank::Bank(){
    this->state = NS_BANK::BANK_STATE::CLOSED;
    bank_id = 0;
    bankGroup_id = 0;
}


int Bank::Init(uint64_t bankGroup_id, uint64_t bank_id, IRankTiming* rank_timing) {

    this->bank_id = bank_id;
    this->bankGroup_id = bankGroup_id;
    this->state = NS_BANK::BANK_STATE::CLOSED;
    this->expectedTime.activate_time = 0; // 初始化预期激活时间
    this->expectedTime.precharge_time = 0; // 初始化预期预充电
    this->expectedTime.rw_time = 0; // 初始化预期读写时间

    this->last_row_id = 0; // 初始化最近访问的行ID
    this->last_column_id = 0; // 初始化最近访问的列ID

    this->rank_timing = rank_timing;
    // std::cout << "Bank " << bank_id << " in BankGroup " << bankGroup_id << " initialized" << std::endl;

    return 0;
}

void Bank::setState(NS_BANK::BANK_STATE state){
    this->state = state;
}

NS_BANK::BANK_STATE Bank::getState(){
    return this->state;
}

void Bank::setBankID(uint64_t bank_id){
    this->bank_id = bank_id;
}

uint64_t Bank::getBankID(){
    return this->bank_id;
}


uint64_t Bank::Process(DRAMCommand &cmd, uint64_t time, const AddressMappingConfig *amp){

    std::cout <<"Bank::Process "
              << ", row_id: " << cmd.row_id 
              << ", at time: " << time << std::endl;

    uint64_t delay = 0;

    if(isNeedPreCharge(cmd.row_id, time)) {
        // 如果需要预充电，先进行预充电
        delay += issuePrecharge(time, amp);
        std::cout << "Bank::Process: Precharge command processed for row_id: " << cmd.row_id << " with delay: " << delay << std::endl;
    }

    if(isNeedActive(cmd.row_id, time)) {
        // 如果需要激活，进行激活

        // 先检查
        delay += issueActive(time+delay, amp);
        std::cout << "Bank::Process: Activate command processed for row_id: " << cmd.row_id << " with delay: " << delay << std::endl;
    }

    if(isNeedRW()) {
        // 如果需要读写，进行读写操作

        std::cout << "Bank::Process: Before RW is: " << time + delay << std::endl;

        std::cout << "Bank::Process: Bank state is: " 
                  << (this->state == NS_BANK::BANK_STATE::OPEN ? " open " : " close ") 
                  << ", last_row_id: " << this->last_row_id 
                  << ", last_column_id: " << this->last_column_id 
                  << std::endl;
        if(cmd.type == CommandType::READ) {
            delay += issueRead(cmd, time+delay, amp);
            std::cout << "Bank::Process: Read command processed for row_id: " << cmd.row_id << " with delay: " << delay << std::endl;
        } else {
            delay += issueWrite(cmd, time+delay, amp);
            std::cout << "Bank::Process: Write command processed for row_id: " << cmd.row_id << " with delay: " << delay << std::endl;           
        }
    }


    return delay; // 返回处理延迟
}




bool Bank::isNeedPreCharge(uint64_t row_id, uint64_t time){
    bool result = false;
    std::cout << "Bank::isNeedPreCharge called with row_id: " << row_id << " at time: " << time << std::endl;
    std::cout << "Bank::isNeedPreCharge: Current state is: " << (this->state == NS_BANK::BANK_STATE::OPEN ? " open ": " close ") << ", last_row_id: " << this->last_row_id << std::endl;
    if(this->state == NS_BANK::BANK_STATE::OPEN && this->last_row_id != row_id) {
        // 如果当前状态是OPEN且行ID不同，则需要预充电
        result = true;

        std::cout << "Bank::isNeedPreCharge: Precharge needed for row_id: " << row_id << " at time: " << time << std::endl;
    }

    return result;
}

bool Bank::isNeedActive(uint64_t row_id, uint64_t time){
    bool result = false;
    if(this->state == NS_BANK::BANK_STATE::CLOSED || this->last_row_id != row_id) {
        // 如果当前状态是CLOSED或行ID不同，则需要激活
        result = true;
        std::cout << "Bank::isNeedActive: Activate needed for row_id: " << row_id << " at time: " << time << std::endl;
    }

    return result;
}



bool Bank::isNeedRW(){
    bool result = false;
    if(this->state == NS_BANK::BANK_STATE::OPEN) {
        // 如果当前状态是OPEN，则需要读写
        result = true;
        std::cout << "Bank::isNeedRW: Read/Write needed at time." << std::endl;
    }

    return result;
}

uint64_t Bank::issuePrecharge(uint64_t time, const AddressMappingConfig *amp) {
    uint64_t delay = 0;
    
    if(time < this->expectedTime.precharge_time) {
        // 如果当前时间小于预期预充电时间，则需要等待
        delay += this->expectedTime.precharge_time - time; // 等待预充电时间
        std::cout << "Bank::issuePrecharge: Waiting for expected precharge time: " << this->expectedTime.precharge_time << " at time: " << time << std::endl;
    }
    delay += amp->getTRP(); // 添加预充电延迟
    this->expectedTime.precharge_time = time + delay; // 更新预期预充电时间
    // this->expectedTime.activate_time = time + delay; // 更新预期激活时间
    // this->expectedTime.rw_time = time + delay; // 更新预期读写
    this->state = NS_BANK::BANK_STATE::CLOSED; // 将状态设置为 CLOSED

    return delay;
}

uint64_t Bank::issueActive(uint64_t time, const AddressMappingConfig *amp) {
    uint64_t delay = 0;

    if(time < this->expectedTime.activate_time) {
        // 如果当前时间小于预期激活时间，则需要等待
        delay += this->expectedTime.activate_time - time; // 等待激活时间
        std::cout << "Bank::issueActive: Waiting for expected activate time: " << this->expectedTime.activate_time << " at time: " << time << std::endl;
    }
    // delay += amp->getTRCD(); // 添加激活延迟
    // std::cout << "Bank::issueActive: Activating bank at time: " << time << " with delay: " << delay << std::endl;
    // this->expectedTime.activate_time = time + delay; // 更新预期激活时间
    // std::cout << "Bank::issueActive: Expected activate time updated to: " << this->expectedTime.activate_time << std::endl;
    // this->expectedTime.rw_time = time + delay; // 更新预期读写时间
    // std::cout << "Bank::issueActive: Expected read/write time updated to: " << this->expectedTime.rw_time << std::endl;


    this->expectedTime.activate_time = time + delay + amp->getTRAS() + amp->getTRP(); // 更新预期激活时间
    std::cout << "Bank::issueActive: Expected activate time updated to: " << this->expectedTime.activate_time << std::endl;
    this->expectedTime.rw_time = time + delay + amp->getTRCD(); // 更新预期读写时间
    std::cout << "Bank::issueActive: Expected read/write time updated to: " << this->expectedTime.rw_time << std::endl;
    this->expectedTime.precharge_time = time + delay + amp->getTRAS(); // 更新预期预充电时间
    std::cout << "Bank::issueActive: Expected precharge time updated to: " << this->expectedTime.precharge_time << std::endl;
    
    this->setState(NS_BANK::BANK_STATE::OPEN); // 设置状态为 OPEN
    std::cout << "Bank::issueActive: Bank state set to OPEN" << std::endl;

    std::cout << "Bank::issueActive: after activate, state is: " << (this->state == NS_BANK::BANK_STATE::OPEN ? " open ": " close ") << std::endl;

    uint64_t real_delay = this->rank_timing->getRankRRDConstrain(this->bankGroup_id, this->bank_id, time + delay);
    std::cout << "Bank::issueActive: real_delay from getRankRRDConstrain is: " << real_delay << std::endl;
    return real_delay;
}



uint64_t Bank::issueRead(DRAMCommand &cmd, uint64_t time, const AddressMappingConfig *amp) {

    std::cout << "Bank::issueRead: Issuing read command at time: " << time << std::endl;
    uint64_t delay = 0;

    if(time < this->expectedTime.rw_time) {
        // 如果当前时间小于预期读写时间，则需要等待
        delay += this->expectedTime.rw_time - time; // 等待读写时间
    }
    delay += amp->getTAL() + amp->getTCL() + amp->getTBurstCycle(); // 添加读请求的延迟
    this->expectedTime.rw_time = time + delay; // 更新预期读写时间
    this->expectedTime.precharge_time = this->expectedTime.rw_time; // 更新预期预充电时间
    this->last_row_id = cmd.row_id; // 更新最近访问的行ID
    this->last_column_id = cmd.column_id; // 更新最近访问的列ID


    std::cout << "Bank::issueRead: Expected read/write time updated to: " << this->expectedTime.rw_time << std::endl;
    std::cout << "Bank::issueRead: Expected precharge time updated to: " << this->expectedTime.precharge_time << std::endl;
    std::cout << "Bank::issueRead: Last row ID updated to: " << this->last_row_id << std::endl;
    std::cout << "Bank::issueRead: Last column ID updated to: " << this->last_column_id << std::endl;   


    std::cout << "Bank::issueread: delay is: " << delay << std::endl;

    std::cout << "Bank::issueRead: after read, state is: " << (this->state == NS_BANK::BANK_STATE::OPEN ? " open ": " close ") << std::endl;

    return delay;
}




uint64_t Bank::issueWrite(DRAMCommand &cmd, uint64_t time, const AddressMappingConfig *amp) {
    uint64_t delay = 0;

    if(time < this->expectedTime.rw_time) {
        // 如果当前时间小于预期读写时间，则需要等待
        delay += this->expectedTime.rw_time - time; // 等待读写时间
    }
    delay += amp->getTAL() + amp->getTCWL() + amp->getTBurstCycle(); // 添加写请求的延迟
    this->expectedTime.rw_time = time + delay; // 更新预期读写时间
    this->expectedTime.precharge_time = this->expectedTime.rw_time; // 更新预期预充电时间
    this->last_row_id = cmd.row_id; // 更新最近访问的行ID
    this->last_column_id = cmd.column_id; // 更新最近访问的列ID

    return delay;
}

